


inline void CMtLogFunc::StrFormatA(std::string& str, const char* szFormat, va_list argList)
{
	assert(szFormat);
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
	static const int kBufGrup = 256;

	char szBufFmt[kBufGrup];
	int nLen = _vsnprintf(szBufFmt, kBufGrup, szFormat, argList);
	if (nLen > -1 && nLen < kBufGrup)
	{
		str = szBufFmt;
		return;
	}

	char* pBufNowFmt = NULL;
	int nBufNowSize = kBufGrup;
	for (;;)
	{
		if (pBufNowFmt) free(pBufNowFmt);
		nBufNowSize = nBufNowSize * 2;
		pBufNowFmt = (char*)malloc(sizeof(char)*nBufNowSize);
		int nLen = _vsnprintf(pBufNowFmt, nBufNowSize, szFormat, argList);
		if (nLen > -1 && nLen < nBufNowSize) break;
	}

	str = pBufNowFmt;
	if (pBufNowFmt) free(pBufNowFmt);
	return;

#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
	int nLength = _vscprintf(szFormat, argList);
	str.resize(nLength);//must nLength
	vsprintf_s(&(str[0]), nLength + 1, szFormat, argList);
#endif
	return;
}

inline void CMtLogFunc::StrFormatA(std::string& str, const char* szFormat, ...)
{
	assert(szFormat);
	va_list argList;
	va_start(argList, szFormat);
	CMtLogFunc::StrFormatA(str, szFormat, argList);
	va_end(argList);
}

inline void CMtLogFunc::StrFormatW(std::wstring& str, const wchar_t* szFormat, va_list argList)
{
	assert(szFormat);
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
	static const int kBufGrup = 256;

	wchar_t szBufFmt[kBufGrup];
	int nLen = _vsnwprintf(szBufFmt, kBufGrup, szFormat, argList);
	if (nLen > -1 && nLen < kBufGrup)
	{
		str = szBufFmt;
		return;
	}

	wchar_t* pBufNowFmt = NULL;
	int nBufNowSize = kBufGrup;
	for (;;)
	{
		if (pBufNowFmt) free(pBufNowFmt);
		nBufNowSize = nBufNowSize * 2;
		pBufNowFmt = (wchar_t*)malloc(sizeof(wchar_t)*nBufNowSize);
		int nLen = _vsnwprintf(pBufNowFmt, nBufNowSize, szFormat, argList);
		if (nLen > -1 && nLen < nBufNowSize) { break; }
	}

	str = pBufNowFmt;
	if (pBufNowFmt) free(pBufNowFmt);
	return;

#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
	int nLength = _vscwprintf(szFormat, argList);
	str.resize(nLength);//must nLength
	vswprintf_s(&(str[0]), nLength + 1, szFormat, argList);
#endif
	return;
}

inline void CMtLogFunc::StrFormatW(std::wstring& str, const wchar_t* szFormat, ...)
{
	assert(szFormat);
	va_list argList;
	va_start(argList, szFormat);
	CMtLogFunc::StrFormatW(str, szFormat, argList);
	va_end(argList);
}


inline void CMtLogFunc::StrAToW(const std::string& a, std::wstring& w)
{
	const char* pA = a.c_str();
	int nBytes = MultiByteToWideChar(CP_ACP, 0, pA, -1, NULL, 0);
	w.resize(nBytes - 1);
	int nBytes2 = MultiByteToWideChar(CP_ACP, 0, pA, -1, &(w[0]), nBytes);
}


inline void CMtLogFunc::GetFileName(const char *pszFilePath, std::string& strRes)
{
	std::string strRes1 = pszFilePath;
	size_t nR = strRes1.rfind('\\');
	if ((nR != std::string::npos) && (nR + 1 < strRes1.size()))
	{
		strRes = strRes1.substr(nR + 1);
	}
}

inline CMtLogFunc::CMtLogFunc(int nLevel, const char* file, const char* fn, int line)
{
	m_fn = fn;
	m_file = file;
	m_line = line;
	m_nLevel = nLevel;
}

inline CMtLogFunc::CMtLogFunc(int nLevel)
{
	m_fn = NULL;
	m_file = NULL;
	m_line = -1;
	m_nLevel = nLevel;
}

inline void CMtLogFunc::OutMsg(const char * szFormat, ...)
{
	assert(szFormat);

	std::string sMsg;
	va_list argList;
	va_start(argList, szFormat);
	CMtLogFunc::StrFormatA(sMsg, szFormat, argList);
	va_end(argList);

	SYSTEMTIME tm;
	GetLocalTime(&tm);

	std::string sMsgAll;

	static char *strLvlxA[] = {
		"Trace   : ",
		"Debug   : ",
		"Info    : ",
		"Warn    : ",
		"Error** : ",
		"Criti!! : ",
	};

	if (m_line == -1)
	{
		CMtLogFunc::StrFormatA(sMsgAll, "%02d-%02d%02d-%02d:%02d:%02d-%03d %s %s\r\n",
			tm.wYear, tm.wMonth, tm.wDay, tm.wHour, tm.wMinute, tm.wSecond, tm.wMilliseconds,
			strLvlxA[m_nLevel], sMsg.c_str()
		);
		LogmtMsgA(m_nLevel, sMsgAll.c_str());
		return;
	}

	std::string s1;
	CMtLogFunc::GetFileName(m_file, s1);

	int nEmptySpace=80-sMsg.size()-34;
	if(nEmptySpace<4)
	{
		nEmptySpace=4;
	}
	std::string strEmptySPace(nEmptySpace,' ');

	CMtLogFunc::StrFormatA(sMsgAll, "%02d-%02d%02d-%02d:%02d:%02d-%03d %s %s%sFs:%s Ln:%05d Td:%05d %s%s\r\n",
		tm.wYear, tm.wMonth, tm.wDay, tm.wHour, tm.wMinute, tm.wSecond, tm.wMilliseconds,
		strLvlxA[m_nLevel],
		sMsg.c_str(),
		strEmptySPace.c_str(),
		s1.c_str(),
		m_line,
		GetCurrentThreadId(),
		m_fn ? "Fn:" : "",
		m_fn ? m_fn : ""
	);
	LogmtMsgA(m_nLevel, sMsgAll.c_str());
}



inline void CMtLogFunc::OutMsg(const wchar_t * szFormat, ...)
{
	assert(szFormat);

	std::wstring sMsg;
	va_list argList;
	va_start(argList, szFormat);
	CMtLogFunc::StrFormatW(sMsg, szFormat, argList);
	va_end(argList);

	SYSTEMTIME tm;
	GetLocalTime(&tm);

	std::wstring sMsgAll;

	static wchar_t *strLvlxA[] = {
		L"Trace   : ",
		L"Debug   : ",
		L"Info    : ",
		L"Warn    : ",
		L"Error** : ",
		L"Criti!! : ",
	};

	if (m_line == -1)
	{
		CMtLogFunc::StrFormatW(sMsgAll, L"%02d-%02d%02d-%02d:%02d:%02d-%03d %s %s\r\n",
			tm.wYear, tm.wMonth, tm.wDay, tm.wHour, tm.wMinute, tm.wSecond, tm.wMilliseconds,
			strLvlxA[m_nLevel], sMsg.c_str()
		);

		LogmtMsgW(m_nLevel, sMsgAll.c_str());
		return;
	}

	std::string s1a;
	CMtLogFunc::GetFileName(m_file, s1a);
	std::wstring s1;
	CMtLogFunc::StrAToW(s1a, s1);

	std::wstring m_fnw;
	if (m_fn)
	{
		CMtLogFunc::StrAToW(m_fn, m_fnw);
	}

	int nEmptySpace=80-sMsg.size()-34;
	if(nEmptySpace<4)
	{
		nEmptySpace=4;
	}
	std::wstring strEmptySPace(nEmptySpace,' ');

	CMtLogFunc::StrFormatW(sMsgAll, L"%02d-%02d%02d-%02d:%02d:%02d-%03d %s %s%sFs:%s Ln:%05d Td:%05d %s%s\r\n",
		tm.wYear, tm.wMonth, tm.wDay, tm.wHour, tm.wMinute, tm.wSecond, tm.wMilliseconds,
		strLvlxA[m_nLevel],
		sMsg.c_str(),
		strEmptySPace.c_str(),
		s1.c_str(),
		m_line,
		GetCurrentThreadId(),
		m_fn ? L"Fn:" : L"",
		m_fn ? m_fnw.c_str() : L""
	);

	LogmtMsgW(m_nLevel, sMsgAll.c_str());
}

